#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>

#include "http.h"



// 状态名称
const char *state_names[] = {
    [STATE_START] = "START",
    [STATE_METHOD] = "METHOD",
    [STATE_URI] = "URI",
    [STATE_VERSION] = "VERSION",
    [STATE_HEADER_KEY] = "HEADER_KEY",
    [STATE_HEADER_VALUE] = "HEADER_VALUE",
    [STATE_BODY] = "BODY",
    [STATE_CR] = "CR",
    [STATE_LF] = "LF",
    [STATE_COMPLETE] = "COMPLETE",
    [STATE_ERROR] = "ERROR"
};

// 方法名称
const char *method_names[] = {
    [HTTP_GET] = "GET",
    [HTTP_POST] = "POST",
    [HTTP_PUT] = "PUT",
    [HTTP_DELETE] = "DELETE",
    [HTTP_HEAD] = "HEAD",
    [HTTP_UNKNOWN] = "UNKNOWN"
};

// 初始化解析器
void init_parser(HttpParser *parser) {
    memset(parser, 0, sizeof(HttpParser));
    parser->state = STATE_START;
    parser->content_length = -1; // 初始化为-1表示未设置
}

// 检查字符是否为有效的令牌字符
int is_token_char(char c) {
    return c > 32 && c < 127 && c != '(' && c != ')' && c != '<' && 
           c != '>' && c != '@' && c != ',' && c != ';' && c != ':' && 
           c != '\\' && c != '"' && c != '/' && c != '[' && c != ']' && 
           c != '?' && c != '=' && c != '{' && c != '}';
}

// 状态机实现
ParserState http_parse(HttpParser *parser, char c) {
    switch (parser->state) {
        case STATE_START:
            if (is_token_char(c)) {
                parser->state = STATE_METHOD;
                parser->method = HTTP_UNKNOWN;
                parser->uri[0] = '\0';
                parser->version[0] = '\0';
                parser->cur_key[0] = c;
                parser->cur_key[1] = '\0';
            } else if (c != ' ' && c != '\r' && c != '\n') {
                parser->state = STATE_ERROR;
            }
            break;

        case STATE_METHOD:
            if (c == ' ') {
                parser->state = STATE_URI;
                parser->uri[0] = '\0';
                
                // 识别HTTP方法
                if (strcmp(parser->cur_key, "GET") == 0) parser->method = HTTP_GET;
                else if (strcmp(parser->cur_key, "POST") == 0) parser->method = HTTP_POST;
                else if (strcmp(parser->cur_key, "PUT") == 0) parser->method = HTTP_PUT;
                else if (strcmp(parser->cur_key, "DELETE") == 0) parser->method = HTTP_DELETE;
                else if (strcmp(parser->cur_key, "HEAD") == 0) parser->method = HTTP_HEAD;
                else parser->method = HTTP_UNKNOWN;
                
                parser->cur_key[0] = '\0';
            } else if (is_token_char(c)) {
                strncat(parser->cur_key, &c, 1);
            } else {
                parser->state = STATE_ERROR;
            }
            break;

        case STATE_URI:
            if (c == ' ') {
                parser->state = STATE_VERSION;
                parser->version[0] = '\0';
            } else if (c == '\r' || c == '\n') {
                parser->state = STATE_ERROR;
            } else {
                strncat(parser->uri, &c, 1);
            }
            break;

        case STATE_VERSION:
            if (c == '\r') {
                parser->state = STATE_CR;
            } else if (c == '\n') {
                parser->state = STATE_LF;
            } else {
                strncat(parser->version, &c, 1);
            }
            break;

        case STATE_HEADER_KEY:
            if (c == ':') {
                parser->state = STATE_HEADER_VALUE;
                parser->cur_value[0] = '\0';
            } else if (c == '\r') {
                parser->state = STATE_CR;
            } else if (is_token_char(c) || c == '-') {
                strncat(parser->cur_key, &c, 1);
            } else {
                parser->state = STATE_ERROR;
            }
            break;

        case STATE_HEADER_VALUE:
            if (c == '\r') {
                // 完成一个头部解析
                parser->header_count++;
                if (strcasecmp(parser->cur_key, "Content-Length") == 0) {
                    parser->content_length = atoi(parser->cur_value);
                }
                parser->cur_key[0] = '\0';
                parser->state = STATE_CR;
            } else if (c == '\n') {
                parser->state = STATE_ERROR;
            } else if (c != ' ' || parser->cur_value[0] != '\0') {
                // 跳过值前的空白
                strncat(parser->cur_value, &c, 1);
            }
            break;

        case STATE_CR:
            if (c == '\n') {
                parser->state = STATE_LF;
            } else {
                parser->state = STATE_ERROR;
            }
            break;

        case STATE_LF:
            if (c == '\r') {
                parser->state = STATE_CR;  // 第二个CR，可能表示头部结束
            } else if (c == '\n') {
                // 连续CRLF表示头部结束
                if (parser->content_length > 0) {
                    parser->state = STATE_BODY;
                    parser->body_index = 0;
                } else {
                    parser->state = STATE_COMPLETE;
                }
            } else {
                parser->state = STATE_HEADER_KEY;
                parser->cur_key[0] = c;
                parser->cur_key[1] = '\0';
                parser->cur_value[0] = '\0';
            }
            break;

        case STATE_BODY:
            parser->body[parser->body_index++] = c;
            if (parser->body_index >= parser->content_length) {
                parser->body[parser->body_index] = '\0';
                parser->state = STATE_COMPLETE;
            }
            break;

        default:
            break;
    }

    return parser->state;
}

// 获取终端宽度
int get_terminal_width() {
    struct winsize w;
    ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
    return w.ws_col;
}

// 打印分隔线
void print_separator() {
    int width = get_terminal_width();
    for (int i = 0; i < width; i++) {
        putchar('-');
    }
    putchar('\n');
}

// 打印解析器状态
void print_parser_state(HttpParser *parser, char current_char) {
    printf("\n");
    print_separator();
    
    // 打印当前状态和字符
    printf(COLOR_CYAN "当前状态: %s" COLOR_RESET, state_names[parser->state]);
    
    if (parser->state != STATE_COMPLETE && parser->state != STATE_ERROR) {
        printf(" | 当前字符: ");
        if (current_char == '\r') {
            printf(COLOR_YELLOW "'\\r'" COLOR_RESET);
        } else if (current_char == '\n') {
            printf(COLOR_YELLOW "'\\n'" COLOR_RESET);
        } else if (isprint(current_char)) {
            printf(COLOR_YELLOW "'%c'" COLOR_RESET, current_char);
        } else {
            printf(COLOR_YELLOW "0x%02X" COLOR_RESET, current_char);
        }
    }
    printf("\n");
    print_separator();
    
    // 打印解析结果
    printf(COLOR_GREEN "HTTP方法: %s\n", method_names[parser->method]);
    printf("URI: %s\n", parser->uri);
    printf("HTTP版本: %s\n", parser->version);
    printf("头部字段数: %d\n", parser->header_count);
    
    if (parser->content_length > 0) {
        printf("内容长度: %d\n", parser->content_length);
    }
    
    if (parser->state == STATE_COMPLETE && parser->content_length > 0) {
        printf("消息体: %s\n", parser->body);
    }
    
    print_separator();
    
    // 打印状态图
    printf(COLOR_MAGENTA "状态机流程:\n");
    printf("START → METHOD → URI → VERSION → (HEADER_KEY → HEADER_VALUE)* → BODY? → COMPLETE\n");
    printf("关键转换点: \\r\\n\\r\\n 标识头部结束\n");
    print_separator();
    printf(COLOR_RESET);
}

// 演示HTTP解析
void demo_http_parsing() {
    // 模拟HTTP请求数据
    const char *http_request = 
        "POST /api/v1/users HTTP/1.1\r\n"
        "Host: example.com\r\n"
        "User-Agent: DemoClient/1.0\r\n"
        "Content-Type: application/json\r\n"
        "Content-Length: 28\r\n"
        "\r\n"
        "oohhhhhhhhhhhhhhh\r\n\r\n";
    
    HttpParser parser;
    init_parser(&parser);
    
    printf(COLOR_BLUE "开始解析HTTP请求...\n" COLOR_RESET);
    printf(COLOR_YELLOW "请求内容:\n%s\n" COLOR_RESET, http_request);
    print_separator();
    
    size_t len = strlen(http_request);
    for (size_t i = 0; i < len; i++) {
        char c = http_request[i];
        ParserState prev_state = parser.state;
        ParserState new_state = http_parse(&parser, c);
        
        // 只有在状态变化时显示
        if (prev_state != new_state || i == 0) {
            system("clear");
            print_parser_state(&parser, c);
            printf("已处理字节: %zu/%zu (%.1f%%)\n", i+1, len, (i+1)*100.0/len);
            print_separator();
            usleep(200000); // 200ms延迟以便观察
        }
        
        if (new_state == STATE_COMPLETE) {
            printf(COLOR_GREEN "\n解析完成!\n" COLOR_RESET);
            break;
        } else if (new_state == STATE_ERROR) {
            printf(COLOR_RED "\n解析错误! 位置: %zu\n" COLOR_RESET, i);
            break;
        }
    }
}

// // 主函数
// int main() {
//     printf(COLOR_BLUE "HTTP协议状态机解析器演示\n" COLOR_RESET);
//     printf("本程序展示如何使用C语言实现基于状态机的HTTP协议解析器\n\n");
    
//     demo_http_parsing();
    
//     printf("\n演示结束。\n");
//     return 0;
// }